package com.hcj.springcloud.socket;

import lombok.extern.slf4j.Slf4j;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.time.LocalDateTime;

/**
 * 客户端
 */
@Slf4j
public class RpcClient<T> {


    /**
     * jdk代理: 获取远程代理对象
     *
     * @param service
     * @param socketAddress
     * @param <T>
     * @return
     */
    public static <T> T getRemoteProxyObj(final Class<T> service, final InetSocketAddress socketAddress) {
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Socket socket = null;
                        ObjectInputStream input = null;
                        ObjectOutputStream out = null;
                        try {
                            socket = new Socket();
                            socket.connect(socketAddress);
                            out = new ObjectOutputStream(socket.getOutputStream());
                            // 按约定的顺序，发送参数
                            out.writeUTF(service.getSimpleName());
                            out.writeUTF(method.getName());
                            out.writeObject(method.getParameterTypes());
                            out.writeObject(args);
                            log.info("客户端发送：serviceName:{}", service.getSimpleName());
                            log.info("客户端发送：methodName:{}", method.getName());
                            log.info("客户端发送：parameterTypes:{}", method.getParameterTypes());
                            log.info("客户端发送：args:{}", args);
                            // 获取结果
                            input = new ObjectInputStream(socket.getInputStream());
                            return input.readObject();
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                input.close();
                                out.close();
                                socket.close();
                            } catch (Exception e) {
                                System.out.println("资源释放异常" + LocalDateTime.now());
                            }
                        }
                        return null;
                    }
                });
    }
}
